package com.xiyuan.smartutils.seqs;

import com.xiyuan.smartutils.Longs;
import com.xiyuan.smartutils.StrUtils;

import java.util.concurrent.atomic.AtomicLong;

/**
 * 整型序列值，默认从1从0x7FFFFFFF(最大值)<br>
 * <br>
 * 1、支持指定len/max两种方式来指定最大值，注意max时使用长整型，如999L，999表示长度<br>
 * 2、注意：本类不会验证min/max/len/seq四值在初始化时的值问题，要谨慎使用
 *
 * @version v1.0.0 @author lgz 2017-8-27 新建与整理
 */
public class Sequence {
    // 最小最大值必须构造即指定，不支持中途修改
    private final long min;
    private final long max;
    private final int len;
    
    // 子类可见，用于子类重写next等
    
    protected AtomicLong sequence = new AtomicLong();
    
    /******************************************************************************/
    // 构造函数&设置长度方法
    /******************************************************************************/
    
    /**
     * 从1到0x7FFFFFFF
     */
    public Sequence() {
        this(1, Integer.MAX_VALUE, 1);
    }
    
    /**
     * 从min 开始到Long.MAX_VALUE
     */
    public Sequence(long seq) {
        this(seq, Long.MAX_VALUE, seq);
    }
    
    /**
     * 从1到len个19
     */
    public Sequence(int len) {
        this(1, Longs.getMax(len), 1);
    }
    
    /**
     * 从min到max
     */
    public Sequence(int min, int max) {
        this(min, max, 1);
    }
    
    /**
     * 从min到max
     */
    public Sequence(long min, long max) {
        this(min, max, 1);
    }
    
    
    /**
     * 从min到max，指定初始值
     */
    public Sequence(int min, int max, int seq) {
        this(min, max, (long) seq);
    }
    
    /**
     * 绝大多数的情况下不会设置错误，所以没有作验证，防止不明所以的NoClassDefFoundError
     */
    protected Sequence(long min, long max, long seq) {
        this.min = min;
        this.max = max;
        this.len = Longs.length(max);
        this.sequence.set(seq);
        if (seq < min) {this.sequence.set(seq);}
        
        this.init();
    }
    
    /**
     * 构造函数时子类可选重写初始化
     */
    protected void init() {
    }
    
    /******************************************************************************/
    // 公开的next方法
    /******************************************************************************/
    
    /**
     * 下一个长整数
     */
    public long next() {
        // synchronized (this) {
        chkSequence();
        return sequence.getAndIncrement();
        // }
    }
    
    /**
     * 下一个整数
     */
    public int nextInt() {
        return (int) next();
    }
    
    /**
     * 下一个整数前补0的定长字符串
     */
    public String nextString() {
        return StrUtils.prefixZero(next(), len);
    }
    
    /**
     * 获取当前序列
     */
    public long current() {
        return sequence.get();
    }
    
    /**
     * 获取当前序列,固定长度前缀补0
     */
    public String currentFixed() {
        return StrUtils.prefixZero(sequence.get(), len);
    }
    
    /**
     * 重置序列
     */
    public final void reset() {
        this.sequence.set(this.min);
    }
    /******************************************************************************/
    // 当前参数值
    
    /******************************************************************************/
    
    public long getMin() {
        return min;
    }
    
    public long getMax() {
        return max;
    }
    
    public int getLen() {
        return len;
    }
    
    /******************************************************************************/
    // 子类调用的方法
    /******************************************************************************/
    
    /**
     * 检查序列号是否回归，注意：子类需同步锁
     */
    protected void chkSequence() {
        long curr = sequence.get();
        if (curr <= min || curr > max) {
            sequence.set(min);// 0x7FFFFFFF+1=负数<0，取sequence<=min，其他取sequence>max
        }
    }
    
    /**
     * 设置序列号值，一般用于初始化时
     */
    protected void setSequence(long seq) {
        if (seq < min || seq > max) {return;}
        sequence.set(seq);
    }
}
